home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / src / modes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-20  |  47.4 KB  |  1,963 lines

  1. /* @(#)src/modes.c    1.38 9/20/92 12:54:56 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *    Copyright (C) 1992  Ronald S. Karr
  6.  * 
  7.  * See the file COPYING, distributed with smail, for restriction
  8.  * and warranty information.
  9.  */
  10.  
  11. /*
  12.  * modes.c:
  13.  *    routines to handle the various modes of operation.  Typically,
  14.  *    these are major functions called directly from main.
  15.  *
  16.  *    external functions: build_host_strings, compute_nobody,
  17.  *                input_signals, processing_signals,
  18.  *                deliver_signals, test_addresses,
  19.  *                perform_deliver_mail, deliver_mail,
  20.  *                daemon_mode, noop_mode, verify_addresses,
  21.  *                print_version, print_copying_file,
  22.  *                print_variables, print_queue, smtp_mode,
  23.  *                fork_wait
  24.  */
  25.  
  26. #define NEED_SOCKETS
  27. #include <stdio.h>
  28. #include <ctype.h>
  29. #include <sys/types.h>
  30. #include "defs.h"
  31. #include <sys/stat.h>
  32. #include <pwd.h>
  33. #include <signal.h>
  34. #include <errno.h>
  35.  
  36. #ifndef ISC_SOCKET_TIME_BUG
  37. # include <time.h>
  38. #endif
  39. #if defined(UNIX_BSD) && !defined(POSIX_OS)
  40. # include <sys/ioctl.h>
  41. #endif
  42. #include <fcntl.h>
  43. #include "smail.h"
  44. #include "alloc.h"
  45. #include "dys.h"
  46. #include "addr.h"
  47. #include "hash.h"
  48. #include "main.h"
  49. #include "log.h"
  50. #include "transport.h"
  51. #include "child.h"
  52. #include "exitcodes.h"
  53. #ifndef DEPEND
  54. # include "extern.h"
  55. # include "debug.h"
  56. # include "error.h"
  57. #endif
  58.  
  59. #if defined(POSIX_OS) || defined(UNIX_BSD) || defined(WAIT_USE_UNION)
  60. # include <sys/wait.h>
  61. #endif
  62. #if (defined(UNIX_BSD) || defined(WAIT_USE_UNION)) &&!defined(NO_WAIT_USE_UNION)
  63. # define STATUS_TYPE    union wait
  64. #else
  65. # define STATUS_TYPE    int
  66. #endif
  67.  
  68. #ifdef ANSI_C
  69. # define VOLATILE volatile
  70. #else
  71. # define VOLATILE /**/
  72. #endif
  73.  
  74. #if !defined(SIGCHLD) && defined(SIGCLD)
  75.  
  76. /* System V uses a different name */
  77. # define SIGCHLD SIGCLD
  78.  
  79. #endif
  80.  
  81. /* variables exported from this file */
  82. int daemon_pid = 0;
  83.  
  84. /* variables local to this file */
  85. #ifdef SIGCHLD
  86. static VOLATILE int smtp_accept_count;
  87. static int smtp_accept_slots;
  88. static VOLATILE int *smtp_pids;
  89. #endif
  90.  
  91. /* variables imported from main.c */
  92. extern char *smtp_service_name;
  93.  
  94. /* functions local to this file */
  95. static int start_daemon();
  96. static void bg_run_queue();
  97. static void do_run_queue();
  98. static void sig_unlink();
  99. static void sig_close();
  100. static void set_queue_only();
  101. static void do_smtp();
  102.  
  103. /*
  104.  * Interactive UNIX 2.2 has a bug in accept().  If accept() is
  105.  * interrupted by an alarm signal, accept() does not return from
  106.  * waiting for a connection with errno set to EINTR.  Unfortunately
  107.  * this is necessary for smail to process its mail queues at regular
  108.  * intervals, as specified with the -q option.
  109.  *
  110.  * Interactive's select() does work correctly, however.  Thus,
  111.  * we use select() to determine when to call accept(), and catch
  112.  * alarm signals out of select(), instead of out of accept().
  113.  */
  114.  
  115. #ifdef ISC_ACCEPT_BUG
  116. fd_set    fds_used, fds_read;
  117. #endif
  118.  
  119.  
  120. /*
  121.  * build_host_strings - build the various types of hostnames
  122.  *
  123.  * always build primary_name.  Build, if NULL, uucp_name, hostnames,
  124.  * and visible_name.
  125.  */
  126. void
  127. build_host_strings()
  128. {
  129.     char *s;
  130.  
  131.     if (hostnames == NULL || uucp_name == NULL) {
  132.     char *real_hostname = compute_hostname();
  133.  
  134.     if (real_hostname == NULL) {
  135.         /* the machine doesn't know who he is */
  136.         panic(EX_SOFTWARE,
  137.           "build_host_strings: Configuration error: hostname unknown");
  138.         /*NOTREACHED*/
  139.     }
  140.  
  141.     if (uucp_name == NULL) {
  142.         /* uucp_name is exactly the real hostname by default */
  143.         uucp_name = real_hostname;
  144.     }
  145.     if (hostnames == NULL) {
  146.         /*
  147.          * by default hostnames is constructed from the real hostname
  148.          * and the visible_domains list.  If visible_domains is NULL,
  149.          * then hostnames is exactly the real hostname.
  150.          */
  151.         if (visible_domains == NULL || visible_domains[0] == '\0') {
  152.         hostnames = real_hostname;
  153.         } else {
  154.         register char *domain = strcolon(visible_domains);
  155.         struct str str;        /* build hostnames here */
  156.  
  157.         STR_INIT(&str);
  158.         str_printf(&str, "%s.%s", real_hostname, domain);
  159.         while (domain = strcolon((char *)NULL)) {
  160.             str_printf(&str, ":%s.%s", real_hostname, domain);
  161.         }
  162.         STR_NEXT(&str, '\0');
  163.         STR_DONE(&str);
  164.  
  165.         hostnames = str.p;
  166.         }
  167.     }
  168.     }
  169.  
  170.     /* primary_name is always the first hostname value */
  171.     primary_name = hostnames;
  172.  
  173.     s = index(hostnames, ':');
  174.     if (s) {
  175.     /* In ANSI C string literals can be put in unwritable text space.
  176.      * Thus, rather than just put a nul byte to separate primary_name
  177.      * and hostnames, we must malloc something and build the
  178.      * primary_name */
  179.     char *new_pd = xmalloc(s - primary_name + 1);
  180.  
  181.     (void) memcpy(new_pd, primary_name, s - primary_name);
  182.     new_pd[s - primary_name] = '\0';
  183.     primary_name = new_pd;
  184.     }
  185.  
  186.     /* visible_name is the primary_name by default */
  187.     if (visible_name == NULL) {
  188.     visible_name = primary_name;
  189.     }
  190. }
  191.  
  192. /*
  193.  * compute_nobody - figure out the nobody uid/gid
  194.  *
  195.  * if `nobody_uid' and `nobody_gid' are defined, use them, otherwise
  196.  * use the login name in `nobody' to determine nobody_uid/gid.
  197.  */
  198. void
  199. compute_nobody()
  200. {
  201.     if (nobody_uid != BOGUS_USER && nobody_gid != BOGUS_GROUP) {
  202.     return;
  203.     }
  204.  
  205.     if (nobody == NULL || nobody[0] == '\0') {
  206.     /*
  207.      * nobody uid/gid not defined.  use something likely to not be
  208.      * in use
  209.      */
  210.     nobody_uid = 32767;
  211.     nobody_gid = 32767;
  212.     } else {
  213.     struct passwd *pw;        /* passwd entry for `nobody' */
  214.  
  215.     pw = getpwbyname(nobody);
  216.     if (pw == NULL) {
  217.         nobody_uid = 32767;
  218.         nobody_gid = 32767;
  219.     } else {
  220.         nobody_uid = pw->pw_uid;
  221.         nobody_gid = pw->pw_gid;
  222.     }
  223.     }
  224. }
  225.  
  226.  
  227. /*
  228.  * input_signals - setup signals to use when reading a message from stdin
  229.  *
  230.  * when reading in a message (for DELIVER_MAIL mode), the spool file should
  231.  * be removed if a SIGHUP or SIGINT comes in, as this supposedly indicates
  232.  * that the user did not complete his input message.  If a SIGTERM comes
  233.  * in then set the queue_only flag, to avoid taking up lots of time.
  234.  */
  235. void
  236. input_signals()
  237. {
  238.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
  239.     (void) signal(SIGHUP, sig_unlink);
  240.     }
  241.     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
  242.     (void) signal(SIGINT, sig_unlink);
  243.     }
  244.     (void) signal(SIGALRM, SIG_IGN);
  245.     (void) signal(SIGTERM, set_queue_only);
  246. }
  247.  
  248. /*
  249.  * processing_signals - signals to use when processing a message
  250.  *
  251.  * in this case, ignore hangups but still allow the user to send an
  252.  * interrupt (if mode is DELIVER_MAIL), up until the time delivery is
  253.  * started.  SIGTERM will close the spool file for now.
  254.  */
  255. void
  256. processing_signals()
  257. {
  258.     (void) signal(SIGHUP, SIG_IGN);
  259.     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
  260.     if (operation_mode == DELIVER_MAIL) {
  261.         (void) signal(SIGINT, sig_unlink);
  262.     } else {
  263.         (void) signal(SIGINT, sig_close);
  264.     }
  265.     }
  266.     (void) signal(SIGALRM, SIG_IGN);
  267.     (void) signal(SIGTERM, sig_close);
  268. }
  269.  
  270. /*
  271.  * delivery_signals - signals to use when delivering a message
  272.  *
  273.  * in this case, ignore everything to avoid stopping in awkward states.
  274.  *
  275.  * TODO: perhaps SIGTERM should set a flag to cause smail to exit between
  276.  *     calls to transport drivers.  Inbetween calls, the state will not
  277.  *     be inconsistent and it should be okay to call close_spool().
  278.  */
  279. void
  280. delivery_signals()
  281. {
  282.     (void) signal(SIGHUP, SIG_IGN);
  283.     (void) signal(SIGINT, SIG_IGN);
  284.     (void) signal(SIGINT, SIG_IGN);
  285.     (void) signal(SIGTERM, SIG_IGN);
  286. }
  287.  
  288. /*
  289.  * sig_unlink - handle a signal by unlinking the spool file.
  290.  *
  291.  * we assume this means that a user didn't really want to send a message
  292.  * after all so we remove the spooled message and exit.
  293.  */
  294. static void
  295. sig_unlink(sig)
  296.     int sig;
  297. {
  298.     (void) signal(sig, SIG_IGN);
  299.     unlink_spool();
  300.     write_log(LOG_TTY, "interrupt: mail message removed");
  301.     exit(EX_OSERR);
  302. }
  303.  
  304. /*
  305.  * set_queue_only - handle a signal by setting the flag queue_only
  306.  *
  307.  * this will cause the message to be read in, but not processed.  Thus,
  308.  * the amount of time spent on processing the message is minimized, while
  309.  * full message processing can be attempted later.
  310.  */
  311. static void
  312. set_queue_only(sig)
  313. {
  314.     (void) signal(sig, set_queue_only);
  315.     queue_only = TRUE;
  316. }
  317.  
  318. /*
  319.  * sig_close - handle a signal by closing the spool file.
  320.  *
  321.  * this will cause processing to stop for the current message.  However,
  322.  * it should be restartable later from a queue run.
  323.  */
  324. static void
  325. sig_close(sig)
  326.     int sig;
  327. {
  328.     (void) signal(sig, SIG_IGN);
  329.     close_spool();
  330.     exit(0);                /* this is not yet an error */
  331. }
  332.  
  333.  
  334. /*
  335.  * test_addresses - read addrs from stdin and route them, for fun
  336.  *
  337.  * Call parse_address and route_remote_addrs to determine which transport
  338.  * is going to be used, and what it will be given, for addresses given on
  339.  * stdin.
  340.  */
  341. void
  342. test_addresses()
  343. {
  344.     char line[4096];            /* plenty of space for input lines */
  345.     int stdin_is_a_tty = isatty(0);
  346.  
  347.     X_PANIC_OKAY();
  348.     if (primary_name == NULL) {
  349.     /* setup all of the hostname information */
  350.     build_host_strings();
  351.     }
  352.  
  353.     while (stdin_is_a_tty && fputs("> ", stdout), gets(line)) {
  354.     struct addr *cur = alloc_addr();
  355.     struct addr *done;
  356.     struct addr *retry;
  357.     struct addr *defer;
  358.     struct addr *fail;
  359.     char *error;
  360.     int form;
  361.     char *lp = line;
  362.  
  363.     strip_rfc822_comments(lp);
  364.     if (*lp == '\0')
  365.         continue;
  366.  
  367.     cur->in_addr = lp;
  368.     if ((cur->work_addr = preparse_address(lp, &error)) == NULL) {
  369.         write_log(LOG_TTY, "syntax error in address: %s", error);
  370.         continue;
  371.     }
  372.  
  373.     done = NULL;
  374.     retry = NULL;
  375.     defer = NULL;
  376.     fail = NULL;
  377.     while (cur &&
  378.            (form = parse_address(cur->work_addr, &cur->target,
  379.                      &cur->remainder, &cur->parseflags)
  380.         ) != FAIL && form != LOCAL)
  381.     {
  382.         cur->flags &= ~ADDR_FORM_MASK;
  383.         cur->flags |= form;
  384.  
  385.         done = NULL;
  386.         retry = NULL;
  387.         defer = NULL;
  388.         fail = NULL;
  389.         if (islocalhost(cur->target)) {
  390.         cur->work_addr = cur->remainder;
  391.         continue;
  392.         }
  393.         route_remote_addrs(cur, &done, &retry, &defer, &fail);
  394.         cur = retry;
  395.     }
  396.  
  397.     if (defer) {
  398.         (void) fprintf(stderr, "%s ... temporary failure: %s\n",
  399.                defer->in_addr, defer->error->message);
  400.         continue;
  401.     }
  402.     if (fail) {
  403.         (void) fprintf(stderr, "%s ... failed: %s\n",
  404.                fail->in_addr, fail->error->message);
  405.         continue;
  406.     }
  407.     if (done) {
  408.         (void) printf("host: %s\naddr: %s\ntransport: %s\n",
  409.               done->next_host? done->next_host: "(local)",
  410.               done->next_addr,
  411.               done->transport->name);
  412.         continue;
  413.     }
  414.  
  415.     switch (form) {
  416.     case FAIL:
  417.         (void) fprintf(stderr, "%s ... parse error: %s\n",
  418.                cur->in_addr, cur->remainder);
  419.         break;
  420.  
  421.     case LOCAL:
  422.         (void) printf("addr: %s\ntransport: local\n", cur->remainder);
  423.         break;
  424.  
  425.     default:
  426.         (void) fprintf(stderr,
  427.                "%s ... internal error in resolve_addr_list\n",
  428.                line);
  429.         break;
  430.     }
  431.     }
  432. }
  433.  
  434.  
  435. /*
  436.  * perform_deliver_mail - read in a message and call deliver_mail()
  437.  *
  438.  * Build a queue file using a message on stdin.  Then, if we are
  439.  * performing immediate delivery of messages, call deliver_mail() to
  440.  * deliver the message.
  441.  */
  442. void
  443. perform_deliver_mail()
  444. {
  445.     char *error;
  446.  
  447.     /* setup signals to remove the spool file on errors */
  448.     X_NO_PANIC();
  449.     input_signals();
  450.     if (queue_message(stdin, dot_usage, recipients, &error) == FAIL) {
  451.     open_system_logs();
  452.     log_spool_errors();
  453.     panic(EX_OSFILE, "incoming mail lost: %s: %s", error, strerrno());
  454.     /*NOTREACHED*/
  455.     }
  456.     X_PANIC_OKAY();
  457.  
  458.     /*
  459.      * if we are running as rmail or rsmtp, then always return a zero
  460.      * exitstatus for errors that occur after successfully spooling
  461.      * the message.  Otherwise, the UUCP subsystem (which calls rmail
  462.      * or rsmtp for mail delivery) may return error messages to the
  463.      * sender, even though smail will now be in complete control of
  464.      * error handling on this message.
  465.      */
  466.     if (prog_type == PROG_RMAIL || prog_type == PROG_RSMTP) {
  467.     force_zero_exitvalue = TRUE;
  468.     }
  469.  
  470.     if (read_message() == NULL) {
  471.     panic(EX_OSFILE, "failed to read queued message");
  472.     /*NOTREACHED*/
  473.     }
  474.  
  475.     /*
  476.      * if a precedence: header is given
  477.      * then change the grade for the mail message
  478.      */
  479.     check_grade();
  480.  
  481.     /*
  482.      * up til now keyboard signals would have caused mail to be
  483.      * removed.  Now that we actually have the message, setup
  484.      * signals appropriate for guarranteeing delivery or panics
  485.      * on errors.
  486.      */
  487.     processing_signals();
  488.  
  489.     /*
  490.      * open the system and per message log files.
  491.      * Do this after spool_message so that panic errors while opening
  492.      * the log files do not dump the mail on the floor.
  493.      */
  494.     open_system_logs();
  495.  
  496.     /*
  497.      * make a log entry for the new message
  498.      */
  499.     log_incoming();
  500.  
  501.     /* log errors generated in spooling the message */
  502.     log_spool_errors();
  503.  
  504.     /* if we are only queuing, we have gone as far as we need to */
  505.     if (queue_only || deliver_mode == QUEUE_MESSAGE) {
  506.     if (debug && dont_deliver) {
  507.         /* unless we are debugging as well */
  508.         DEBUG(DBG_MAIN_LO,
  509.           "debugging is on, -Q (queue_only) flag ignored\n");
  510.     } else {
  511.         if (debug) {
  512.         DEBUG(DBG_MAIN_LO,
  513.               "-Q (queue_only) specified and message is queued\n");
  514.         }
  515.         close_spool();
  516.         return;
  517.     }
  518.     }
  519.  
  520.     /*
  521.      * if we are delivering in background, fork a child to perform
  522.      * delivery and exit.  Ignore this when debugging.
  523.      */
  524.     if (deliver_mode ==  BACKGROUND) {
  525.     int pid;
  526.  
  527.     /* unlock the message in the parent, see lock_message() for details */
  528.     delivery_signals();        /* disassociate from terminal */
  529.     if (error_processing != TERMINAL) {
  530.         (void) fclose(stdin);
  531.     }
  532.     unlock_message();
  533.     pid = fork();
  534.     if (pid < 0) {
  535.         /* fork failed, just leave the queue file there and exit */
  536.         write_log(LOG_TTY, "fork failed: %s, message queued", strerrno());
  537.         close_spool();
  538.         return;
  539.     }
  540.     if (pid > 0) {
  541.         /* in parent process, just return */
  542.         return;
  543.     }
  544. #ifdef POSIX_OS
  545.     (void) setsid();
  546. #else    /* not POSIX_OS */
  547.     (void) setpgrp(0, getpid());
  548. #endif    /* POSIX_OS */
  549.     if (lock_message() == FAIL) {
  550.         /* somebody else grabbed the lock, let them deliver */
  551.         return;
  552.     }
  553.     }
  554.  
  555.     /* read the various configuration files */
  556.     if ((error = read_transport_file()) ||
  557.     (error = read_router_file()) ||
  558.     (error = read_director_file()) ||
  559.     (error = read_qualify_file()) ||
  560.     (error = read_retry_file()))
  561.     {
  562.     panic(EX_OSFILE, "%s", error);
  563.     }
  564.  
  565.     /* setup all of the hostname information */
  566.     build_host_strings();
  567.  
  568.     /* figure out the nobody uid/gid */
  569.     compute_nobody();
  570.  
  571.     /*
  572.      * process the message, find all of the recipients and
  573.      * perform delivery.
  574.      */
  575.     deliver_mail();
  576.  
  577.     /*
  578.      * close the system-wide log files
  579.      */
  580.     close_system_logs();
  581. }
  582.  
  583. /*
  584.  * deliver_mail - oversee the delivery of mail (default mailer operation)
  585.  *
  586.  * Spool the mail, process the header, process the addresses, route,
  587.  * alias expand, deliver remote mail, deliver local mail, process errors.
  588.  */
  589. void
  590. deliver_mail()
  591. {
  592.     struct addr *cur;            /* addr being processed */
  593.     struct addr *next;            /* next addr to process */
  594.     struct addr *fail= NULL;        /* list of failed addrs */
  595.     struct addr *route_list = NULL;    /* list of addrs to route */
  596.     struct addr *defer = NULL;        /* list of deferred addrs */
  597.     struct addr *deliver;        /* addr structures ready to deliver */
  598.     /* transport instances */
  599.     struct assign_transport *assigned_transports = NULL;
  600.     char *error;
  601.     struct identify_addr *sent_errors;    /* addresses previously sent errors */
  602.     struct defer_addr *defer_errors;    /* previous defer messages */
  603.  
  604.     /*
  605.      * preparse all of the recipient addresses given as arguments.
  606.      * If we are extracting addresses from the header, then
  607.      * these addresses are NOT to receive the mail.  To accomplish
  608.      * this, add them to the hash table so they will be ignored
  609.      * later.
  610.      */
  611.     route_list = NULL;
  612.     for (cur = recipients; cur; cur = next) {
  613.     next = cur->succ;
  614.     split_addr_list(cur->in_addr, &route_list);
  615.     }
  616.     for (cur = route_list, route_list = NULL; cur; cur = next) {
  617.     next = cur->succ;
  618.     if ((cur->work_addr =
  619.          preparse_address(cur->in_addr, &error)) == NULL)
  620.     {
  621.         /*
  622.          * ERR_147 - parse error in input address
  623.          *
  624.          * DESCRIPTION
  625.          *      preparse_address() encountered a parsing error in one of
  626.          *      the addresses supplied by the sender.  The specific
  627.          *      error was returned in `error'.
  628.          *
  629.          * ACTIONS
  630.          *      Fail the address and send an error to the sender.
  631.          *
  632.          * RESOLUTION
  633.          *      The sender should supply a valid address.
  634.          */
  635.         cur->error = note_error(ERR_NSENDER|ERR_147,
  636.                     xprintf("parse error %s", error));
  637.         cur->flags &= ~ADDR_FORM_MASK;
  638.         cur->flags |= PARSE_ERROR;
  639.         cur->succ = fail;
  640.         fail = cur;
  641.         continue;
  642.     }
  643.     if (extract_addresses) {
  644.         (void) add_to_hash(cur->work_addr, (char *)NULL, 0, hit_table);
  645.         xfree(cur->work_addr);    /* don't need it anymore */
  646.         xfree((char *)cur);
  647.         continue;
  648.     }
  649.     cur->succ = route_list;
  650.     route_list = cur;
  651.     }
  652.  
  653.     if (extract_addresses) {
  654.     route_list = NULL;        /* don't need them anymore */
  655.     }
  656.  
  657.     /*
  658.      * process_header will perform a preliminary analysis of the
  659.      * header fields.  It will note which standard fields exist
  660.      * and may take addresses from the header.  It will perform
  661.      * some initial processing of the From: lines and, depending
  662.      * upon configuration, may put `,' characters between addresses.
  663.      * Also, some required fields which do not exist will be
  664.      * added, (i.e., From: and To: and Message-Id:).
  665.      */
  666.     if (extract_addresses) {
  667.     error = process_header(&route_list);
  668.     } else {
  669.     error = process_header((struct addr **)NULL);
  670.     }
  671.     if (error) {
  672.     write_log(LOG_MLOG, "error in header: %s", error);
  673.     if (extract_addresses) {
  674.         return_to_sender = TRUE;
  675.         /* notify people of errors, ignoring previously reported errors */
  676.         sent_errors = NULL;
  677.         defer_errors = NULL;
  678.         (void) process_msg_log((struct addr *)NULL, &sent_errors,
  679.                    &defer_errors);
  680.         notify((struct addr *)NULL,    /* no defer or fail list */
  681.            (struct addr *)NULL,
  682.            sent_errors);
  683.         unlink_spool();
  684.     }
  685.     return;
  686.     }
  687.  
  688.     /*
  689.      * given the list of recipient addresses, turn those
  690.      * addresses into more specific destinations, including
  691.      * the transport that is to be used, in the case of
  692.      * addresses destined remote
  693.      */
  694.     deliver = NULL;
  695.     resolve_addr_list(route_list, &deliver, &defer, &fail, TRUE);
  696.  
  697.     if (deliver == NULL && defer == NULL) {
  698.     write_log(LOG_MLOG, "no valid recipients were found for this message");
  699.     return_to_sender = TRUE;
  700.     }
  701.  
  702.     /*
  703.      * remove addresses to which we have already delivered mail and
  704.      * note addresses for which we have already delivered error messages
  705.      */
  706.     sent_errors = NULL;
  707.     defer_errors = NULL;
  708.     deliver = process_msg_log(deliver, &sent_errors, &defer_errors);
  709.  
  710.     /*
  711.      * log failures right now
  712.      */
  713.     if (fail) {
  714.     fail_delivery(fail);
  715.     }
  716.  
  717.     /*
  718.      * assign instances of transports for remote addresses
  719.      */
  720.     assigned_transports = assign_transports(deliver);
  721.  
  722.     /*
  723.      * deliver all of the assigned mail.  Note: call_transport
  724.      * will already have handled log entries for failed addresses.
  725.      */
  726.     delivery_signals();
  727.     call_transports(assigned_transports, &defer, &fail);
  728.     if (defer) {
  729.     defer_delivery(defer, defer_errors);
  730.     }
  731.  
  732.     /*
  733.      * perform error notification for all failed and perhaps some deferred
  734.      * addresses.  Addresses for which we have already sent error messages
  735.      * are ignored.
  736.      */
  737.     notify(defer, fail, sent_errors);
  738.  
  739.     /*
  740.      * tidy up before going away
  741.      */
  742.     if (call_defer_message) {
  743.     /*
  744.      * leave a file in an error/ directory for the system
  745.      * administrator to look at.  This is used for failed error
  746.      * mail and for problems resulting from configuration errors.
  747.      */
  748.     defer_message();
  749.     } else if (some_deferred_addrs) {
  750.     /*
  751.      * leave the file around to be processed by a later queue run.
  752.      * Use this for temporary problems such as being blocked by a
  753.      * locked file, or timeouts waiting for a response from a
  754.      * remote system.
  755.      */
  756.     close_spool();
  757.     } else {
  758.     /*
  759.      * if no requests for deferring of addresses or of the message
  760.      * occured, then we are done with the message.  Thus, unlink
  761.      * the message and the per-message log file.
  762.      */
  763.     unlink_spool();
  764.     unlink_msg_log();
  765.     }
  766. }
  767.  
  768.  
  769. static void daemon_sighup();
  770. static void daemon_sigalrm();
  771. #ifdef SIGCHLD
  772. static void daemon_sigchld();
  773. static void reap_child();
  774. #endif
  775. static int got_sighup;
  776. static int got_sigalrm;
  777.  
  778. #if    defined(HAVE_BSD_NETWORKING)
  779. static void do_daemon_accept();
  780.  
  781. /*
  782.  * daemon_mode - be a daemon waiting for requests
  783.  *
  784.  * Listen on the smtp port for connections.  Accept these connections and
  785.  * read smtp commands from them.
  786.  */
  787. void
  788. daemon_mode()
  789. {
  790.     int ls;                /* listen socket */
  791.     int as;                /* accept socket */
  792.     struct sockaddr_in sin, from;    /* from is currently  */
  793.     struct servent *smtp_service;    /* smtp service file entry */
  794.     int port;
  795.     int accept_err_cnt = 0;
  796. #ifdef ISC_ACCEPT_BUG
  797.     int nsel;
  798. #endif
  799.     int on = 1;
  800.  
  801.     X_PANIC_OKAY();
  802.  
  803.     /*
  804.      * don't use background delivery mode.  Since forked smtp connection
  805.      * handlers are in background anyway, the extra child process level
  806.      * could only serve to mess up the count of child processes kept for
  807.      * comparison with the smtp_accept_max value.
  808.      */
  809.  
  810.     if (deliver_mode == BACKGROUND)
  811.     deliver_mode = FOREGROUND;
  812.  
  813.     /*
  814.      * we aren't interested in the old stdin or stdout, substitute
  815.      * /dev/null
  816.      */
  817.     (void) close(0);
  818.     (void) close(1);
  819.     open("/dev/null", 0);
  820.     dup(0);
  821.  
  822.     /* setup the listen socket */
  823.     if (smtp_service_name == NULL) {
  824.     smtp_service_name = "smtp";
  825.     }
  826.     if (isdigit(smtp_service_name[0])) {
  827.     port = htons(atoi(smtp_service_name));
  828.     } else {
  829.     if ((smtp_service = getservbyname(smtp_service_name, "tcp")) == NULL) {
  830.         write_log(LOG_SYS, "%s/tcp: unknown service", smtp_service_name);
  831.         exitvalue = EX_UNAVAILABLE;
  832.         return;
  833.     }
  834.     port = smtp_service->s_port;
  835.     }
  836.     (void) bzero((char *)&sin, sizeof(sin));
  837.     ls = socket(AF_INET, SOCK_STREAM, 0);
  838.     if (ls < 0) {
  839.     write_log(LOG_SYS, "socket(AF_INET, SOCKSTREAM, 0) failed: %s",
  840.           strerrno());
  841.     exitvalue = EX_OSERR;
  842.     return;
  843.     }
  844.     sin.sin_family = AF_INET;
  845.     sin.sin_addr.s_addr = INADDR_ANY;
  846.     sin.sin_port = port;
  847.  
  848.     /*
  849.      * set SO_REUSEADDR so that the daemon can be restarted while
  850.      * a connection is being handled.  Without this, a connection
  851.      * alone will prevent reuse of the smtp port number for listening
  852.      * purposes.
  853.      */
  854.  
  855.     if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
  856.     write_log(LOG_SYS, "SO_REUSEADDR on failed: %s\n", strerrno());
  857.     exitvalue = EX_OSERR;
  858.     return;
  859.     }
  860.  
  861.     if (bind(ls, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  862.     write_log(LOG_SYS, "bind() failed: %s", strerrno());
  863.     exitvalue = EX_OSERR;
  864.     return;
  865.     }
  866.  
  867.     /*
  868.      * start smail as a background daemon process.  Return in the
  869.      * parent.
  870.      */
  871.     if (start_daemon() != 0) {
  872.     return;
  873.     }
  874.  
  875. #ifdef SIGCHLD
  876.     /* NOTE:  If there is no SIGCHLD we can't reap dead kids!  lose */
  877.     (void) signal(SIGCHLD, daemon_sigchld);
  878.  
  879.     /* assure that max connects is a sane value */
  880.     if (smtp_accept_max < 0 || smtp_accept_max > 4095) {
  881.     smtp_accept_max = 0;
  882.     }
  883.     smtp_accept_slots = smtp_accept_max;
  884.     /* assure that max connects until queue only is a sane value */
  885.     if (smtp_accept_queue < 0 || smtp_accept_queue > 4095) {
  886.     smtp_accept_queue = 0;
  887.     }
  888.     if (smtp_accept_queue > smtp_accept_slots)
  889.     smtp_accept_slots = smtp_accept_queue;
  890.  
  891.     /* allocate space for listener pids (if we're keeping track) */
  892.     if (smtp_pids == NULL && smtp_accept_slots > 0) {
  893.     int i;
  894.  
  895.     smtp_pids = (int *) xmalloc(smtp_accept_slots * sizeof(int));
  896.     for (i = 0; i < smtp_accept_slots; ++i)
  897.         smtp_pids[i] = 0;
  898.     }
  899. #endif /* SIGCHLD */
  900.  
  901.     /* if we are doing queue runs, do one queue run first */
  902.     if (process_queue) {
  903.     bg_run_queue(-1);
  904.     }
  905.  
  906.     /* SIGHUP means re-exec */
  907.     got_sighup = FALSE;
  908.     (void) signal(SIGHUP, daemon_sighup);
  909.  
  910.     /* set the alarm for wakeup time */
  911.     got_sigalrm = FALSE;
  912.     if (process_queue && queue_interval > 0) {
  913. #if defined(UNIX_BSD4_3) || defined(USE_SIGINTERRUPT)
  914.     /*
  915.      * We need to interrupt the accept, so ask for interrupted
  916.      * system calls from SIGALRMs.
  917.      */
  918.     siginterrupt(SIGALRM, 1);
  919. #endif
  920.     (void) signal(SIGALRM, daemon_sigalrm);
  921.     (void) alarm(queue_interval);
  922.     }
  923.  
  924.     /* loop processing connect requests or alarm signals */
  925.     (void) listen(ls, 5);
  926.     for (;;) {
  927.     int len = sizeof(from);
  928.  
  929.     DEBUG1(DBG_MAIN_MID, "listening on port %d...\n",
  930.            ntohs(smtp_service->s_port));
  931.  
  932. #ifdef ISC_ACCEPT_BUG
  933.     FD_ZERO(&fds_used);
  934.     FD_SET(ls, &fds_used);
  935.  
  936.     memcpy(&fds_read, &fds_used, sizeof(&fds_read));
  937.     nsel = select(ls + 1, &fds_read, (char *)0, (char *)0, (char *)0);
  938.     if (nsel < 0) {
  939.         if (errno != EINTR) {
  940.         write_log(LOG_PANIC, "select failed: %s", strerrno());
  941.         continue;
  942.         }
  943.     } else {
  944. #endif    /* ISC_ACCEPT_BUG */
  945.  
  946.     /* get connection */
  947.     as = accept(ls, (struct sockaddr *)&from, &len);
  948.     if (as < 0 && errno != EINTR) {
  949.         write_log(LOG_PANIC, "accept failed: %s", strerrno());
  950.  
  951.         /*
  952.          * for some reason, accept() fails badly (and repeatedly)
  953.          * on some systems.  To prevent the paniclog from filling
  954.          * up, exit if this happens too many times.
  955.          */
  956.  
  957.         sleep(5);
  958.         accept_err_cnt++;
  959.         if (accept_err_cnt == 10) {
  960.             write_log(LOG_PANIC, "too many accept errors, quitting");
  961.             exit(EX_OSERR);
  962.         }
  963.         continue;
  964.     }
  965.     accept_err_cnt = 0;
  966.     if (as >= 0) {
  967. #ifdef SIGCHLD
  968.         if (smtp_accept_max > 0 && smtp_accept_count >= smtp_accept_max) {
  969.         static char *reject[2] = {
  970.           "421 ", " Too many connections; try again later.\r\n"
  971.         };
  972.  
  973.         DEBUG1(DBG_MAIN_MID, "rejecting SMTP connection #%d...\n",
  974.                smtp_accept_count + 1);
  975.         (void) write(as, reject[0], strlen(reject[0]));
  976.         (void) write(as, primary_name, strlen(primary_name));
  977.         (void) write(as, reject[1], strlen(reject[1]));
  978.         (void) close(as);
  979.         continue;
  980.         }
  981. #endif    /* SIGCHLD */
  982.  
  983.         do_daemon_accept(ls, as, &from);
  984.     }
  985.  
  986. #ifdef ISC_ACCEPT_BUG
  987.     }
  988. #endif
  989.  
  990.     if (got_sighup) {
  991.         write_log(LOG_SYS, "pid %d: SIGHUP received, exec(%s)",
  992.               getpid(), smail);
  993.         execv(smail, save_argv);
  994.         panic(EX_UNAVAILABLE, "pid %d: exec of %s failed", getpid());
  995.     }
  996.     if (got_sigalrm) {
  997.         /* if config file have changed, recycle */
  998.         DEBUG(DBG_MAIN_LO, "SIGALRM received, check input queue\n");
  999.         if (is_newconf()) {
  1000.         /* re-exec smail */
  1001.         write_log(LOG_SYS, "pid %d: new config files, exec(%s)",
  1002.               getpid(), smail);
  1003.         execv(smail, save_argv);
  1004.         panic(EX_UNAVAILABLE, "pid %d: exec of %s failed", getpid());
  1005.         /*NOTREACHED*/
  1006.         }
  1007.         /* reopen the log files so that they can be moved and removed */
  1008.         close_system_logs();
  1009.         open_system_logs();
  1010.  
  1011.         /* recache all of the driver info, to get any changes */
  1012. #ifdef SIGCHLD
  1013.         (void) signal(SIGCHLD, SIG_DFL);
  1014. #endif
  1015.         cache_directors();
  1016.         cache_routers();
  1017.         cache_transports();
  1018. #ifdef SIGCHLD
  1019.         (void) signal(SIGCHLD, daemon_sigchld);
  1020. #endif
  1021.  
  1022.         bg_run_queue(ls);        /* do queue run in child process */
  1023.         got_sigalrm = FALSE;
  1024.         (void) alarm(queue_interval);
  1025.     }
  1026.     }
  1027. }
  1028.  
  1029. /*
  1030.  * do_daemon_accept - perform processing for an accepted SMTP connection
  1031.  *
  1032.  * accept SMTP commands in a separate process.
  1033.  */
  1034. static void
  1035. do_daemon_accept(ls, fd, from)
  1036.     int ls;                /* listen socket, must be closed */
  1037.     int fd;                /* connected channel */
  1038.     struct sockaddr_in *from;        /* address of peer */
  1039. {
  1040.     int fd2;                /* dup of connected channel */
  1041.     int pid;
  1042.  
  1043.     DEBUG1(DBG_MAIN_LO, "connection request from [%s]\n",
  1044.        inet_ntoa(from->sin_addr));
  1045.     fd2 = dup(fd);
  1046.     if (fd2 < 0) {
  1047.     FILE *f = fdopen(fd, "w");
  1048.  
  1049.     (void) fprintf(f, "421 %s Connection refused: %s\r\n",
  1050.                primary_name, strerrno());
  1051.     (void) fflush(f);
  1052.     (void) close(fd);
  1053.     return;
  1054.     }
  1055.     pid = fork();
  1056.     if (pid == 0) {
  1057.     FILE *in;            /* input channel */
  1058.     FILE *out;            /* output channel */
  1059.  
  1060.     /* in child process */
  1061.     (void) close(ls);
  1062.     in = fdopen(fd, "r");    /* setup the channels */
  1063.     out = fdopen(fd2, "w");
  1064.  
  1065.     /* no longer ignore kids */
  1066. #ifdef SIGCHLD
  1067.     (void) signal(SIGCHLD, SIG_DFL);
  1068. #endif
  1069.  
  1070.     /* make inet address available in ASCII representation */
  1071.     sender_host_addr = COPY_STRING(inet_ntoa(from->sin_addr));
  1072.  
  1073.     /*
  1074.      * if the number of outstanding child processes exceeds
  1075.      * smtp_accept_queue, then turn on queue_only, so that
  1076.      * mail will not be delivered immediately.
  1077.      */
  1078.  
  1079.     if (smtp_accept_queue > 0 && smtp_accept_count >= smtp_accept_queue) {
  1080.         DEBUG1(DBG_MAIN_MID, "many connections, use queue_only #%d...\n",
  1081.            smtp_accept_count + 1);
  1082.         queue_only = TRUE;
  1083.     }
  1084.  
  1085.     /* do the actual work */
  1086.     do_smtp(in, out);
  1087.  
  1088.     /* done with that transaction */
  1089.     exit(0);
  1090.     }
  1091.     /* in parent process */
  1092.     if (pid < 0) {
  1093.     FILE *f = fdopen(fd, "w");
  1094.  
  1095.     (void) fprintf(f, "421 %s Connection refused: %s\r\n",
  1096.                primary_name, strerrno());
  1097.     (void) fflush(f);
  1098.     }
  1099.     else {
  1100. #ifdef SIGCHLD
  1101.     int i;
  1102.  
  1103.     for (i = 0; i < smtp_accept_slots; ++i) {
  1104.         if (smtp_pids[i] <= 0) {
  1105.         smtp_pids[i] = pid;
  1106.         ++smtp_accept_count;
  1107.         break;
  1108.         }
  1109.     }
  1110. #endif /* SIGCHLD */
  1111.     }
  1112.     (void) close(fd);
  1113.     (void) close(fd2);
  1114. }
  1115.  
  1116. #else    /* not defined(HAVE_BSD_NETWORKING) */
  1117.  
  1118. /*
  1119.  * For systems that don't have sockets, turn daemon mode into
  1120.  * a call to noop_mode().  This will have the desired affect if a
  1121.  * queue run was also requested.  Otherwise, it will simply return.
  1122.  */
  1123. void
  1124. daemon_mode()
  1125. {
  1126.     if (errfile) {
  1127.     (void) fprintf(stderr, "%s: daemon mode not supported\n", program);
  1128.     exitvalue = EX_UNAVAILABLE;
  1129.     }
  1130.     noop_mode();
  1131. }
  1132.  
  1133. #endif    /* not defined(HAVE_BSD_NETWORKING) */
  1134.  
  1135. /*
  1136.  * daemon_sighup - note that we received a SIGHUP signal
  1137.  */
  1138. /*ARGSUSED*/
  1139. static void
  1140. daemon_sighup(sig)
  1141.     int sig;
  1142. {
  1143.     got_sighup = TRUE;
  1144.     (void) signal(SIGHUP, daemon_sighup);
  1145. }
  1146.  
  1147. #ifdef SIGCHLD
  1148. /*
  1149.  * daemon_sigchld - reap dead kids
  1150.  */
  1151. /*ARGSUSED*/
  1152. static void
  1153. daemon_sigchld(sig)
  1154.     int sig;
  1155. {
  1156.     int pid;
  1157.  
  1158. #ifdef POSIX_OS
  1159.     while ((pid = waitpid(-1, (int *)0, WNOHANG)) > 0)
  1160. #else
  1161. #ifdef UNIX_BSD
  1162.     while ((pid = wait3((STATUS_TYPE *)0, WNOHANG, 0)) > 0)
  1163. #else
  1164.     if ((pid = wait((STATUS_TYPE *)0)) > 0)
  1165. #endif
  1166. #endif
  1167.     {
  1168.     reap_child(pid);
  1169.     }
  1170.  
  1171. #ifndef UNIX_BSD
  1172.     (void) signal(sig, daemon_sigchld);
  1173. #endif
  1174. }
  1175.  
  1176. static void
  1177. reap_child(pid)
  1178. int pid;
  1179. {
  1180.     int i;
  1181.  
  1182.     for (i = 0; i < smtp_accept_slots; ++i) {
  1183.     if (smtp_pids[i] == pid) {
  1184.         smtp_pids[i] = 0;
  1185.         if (--smtp_accept_count < 0)
  1186.         smtp_accept_count = 0;
  1187.         break;
  1188.     }
  1189.     }
  1190. }
  1191. #endif    /* SIGCHLD */
  1192.  
  1193. /*
  1194.  * daemon_sigalrm - note that we received a SIGALRM signal
  1195.  */
  1196. /*ARGSUSED*/
  1197. static void
  1198. daemon_sigalrm(sig)
  1199.     int sig;
  1200. {
  1201.     got_sigalrm = TRUE;
  1202.     (void) signal(SIGALRM, daemon_sigalrm);
  1203. }
  1204.  
  1205.  
  1206. /*
  1207.  * noop_mode - perform queue runs once or at intervals
  1208.  *
  1209.  * When the -q flag is specified, or smail is invoked as runq, but -bd
  1210.  * is not specified, then noop_mode() is invoked, which does nothing but
  1211.  * execute run_queue() in background at intervals.  If no sleep interval
  1212.  * is specified, run_queue() is called only once.
  1213.  */
  1214. void
  1215. noop_mode()
  1216. {
  1217.     X_PANIC_OKAY();
  1218.  
  1219.     if (! process_queue) {
  1220.     /* queue procesing not requested, nothing to do */
  1221.     return;
  1222.     }
  1223.  
  1224.     /*
  1225.      * Turn smail process into a daemon, quit if we are in the parent
  1226.      * process.
  1227.      */
  1228.     if (start_daemon() != 0) {
  1229.     return;
  1230.     }
  1231.  
  1232.     /* arrange signals */
  1233.     got_sighup = FALSE;
  1234.     got_sigalrm = FALSE;
  1235. #ifdef SIGCHLD
  1236.     /* NOTE:  If there is no SIGCHLD we can't reap dead kids!  lose */
  1237.     (void) signal(SIGCHLD, daemon_sigchld);
  1238. #endif
  1239.     (void) signal(SIGHUP, daemon_sighup);
  1240.     (void) signal(SIGALRM, daemon_sigalrm);
  1241.  
  1242.     if (debug && queue_interval == 0) {
  1243. #ifdef SIGCHLD
  1244.     (void) signal(SIGCHLD, SIG_DFL);
  1245. #endif
  1246.     do_run_queue();
  1247.     } else {
  1248.     bg_run_queue(-1);
  1249.     }
  1250.     if (queue_interval > 0) {
  1251.     /* get an alarm at intervals */
  1252.     (void) alarm(queue_interval);
  1253.     for (;;) {
  1254.         pause();
  1255.         /* watch for SIGHUP to indicate a recycle */
  1256.         if (got_sighup) {
  1257.         write_log(LOG_SYS, "pid %d: SIGHUP received, exec(%s)",
  1258.                getpid(), smail);
  1259.         execv(smail, save_argv);
  1260.         panic(EX_UNAVAILABLE, "pid %d: exec of %s failed", getpid());
  1261.         /*NOTREACHED*/
  1262.         }
  1263.         if (! got_sigalrm) {
  1264.         continue;
  1265.         }
  1266.  
  1267.         /* reset the alarm condition */
  1268.         got_sigalrm = FALSE;
  1269.  
  1270.         /* if config file have changed, recycle */
  1271.         if (is_newconf()) {
  1272.         write_log(LOG_SYS, "pid %d: new config files, exec(%s)",
  1273.                getpid(), smail);
  1274.         execv(smail, save_argv);
  1275.         panic(EX_UNAVAILABLE, "pid %d: exec of %s failed", getpid());
  1276.         /*NOTREACHED*/
  1277.         }
  1278.         /* reopen the log files so that they can be moved and removed */
  1279.         close_system_logs();
  1280.         open_system_logs();
  1281.  
  1282.         /* recache all of the driver info, to get any changes */
  1283. #ifdef SIGCHLD
  1284.         (void) signal(SIGCHLD, SIG_DFL);
  1285. #endif
  1286.         cache_directors();
  1287.         cache_routers();
  1288.         cache_transports();
  1289. #ifdef SIGCHLD
  1290.         (void) signal(SIGCHLD, daemon_sigchld);
  1291. #endif
  1292.  
  1293.         /* do another queue run */
  1294.         bg_run_queue(-1);
  1295.         (void) alarm(queue_interval);
  1296.     }
  1297.     }
  1298. }
  1299.  
  1300. /*
  1301.  * start_daemon - start a daemon smail process for noop_mode() or
  1302.  *          daemon_mode()
  1303.  *
  1304.  * open system lots, get some system information we can use for
  1305.  * processing each message, and put ourselves in background.
  1306.  *
  1307.  * Return the pid of the child process in the parent, and 0 in the
  1308.  * child.
  1309.  */
  1310. static int
  1311. start_daemon()
  1312. {
  1313.     int pid;
  1314. #if defined(UNIX_BSD) && !defined(POSIX_OS)
  1315.     int fd;
  1316. #endif
  1317.  
  1318.     /* cache some interesting things */
  1319.     open_system_logs();
  1320.     if (primary_name == NULL) {
  1321.     build_host_strings();
  1322.     }
  1323.     compute_nobody();
  1324.  
  1325.     /* disconnect from the controlling terminal, if we are not debugging */
  1326.     if (debug == 0) {
  1327.     pid = fork();
  1328.     if (pid < 0) {
  1329.         write_log(LOG_TTY, "fork() failed: %s", strerrno());
  1330.         exitvalue = EX_OSERR;
  1331.         return pid;
  1332.     }
  1333.     if (pid > 0) {
  1334.         /* in parent process, just exit */
  1335.         return pid;
  1336.     }
  1337. #ifdef POSIX_OS
  1338.     (void) setsid();
  1339. #else    /* not POSIX_OS */
  1340. #ifdef UNIX_BSD
  1341.     (void) setpgrp(0, getpid());
  1342.     fd = open("/dev/tty", O_RDWR);
  1343.     if (fd >= 0) {
  1344.         ioctl(fd, TIOCNOTTY, 0);
  1345.         close(fd);
  1346.     }
  1347. #else
  1348.     (void) setpgrp();
  1349. #endif    /* UNIX_BSD */
  1350. #endif    /* POSIX_OS */
  1351.     if (errfile) {
  1352.         (void) fclose(errfile);
  1353.         errfile = NULL;
  1354.     }
  1355.     if (isatty(fileno(stdout))) {
  1356.         (void) fclose(stdout);
  1357.     }
  1358.     if (isatty(fileno(stdin))) {
  1359.         (void) fclose(stdin);
  1360.     }
  1361.     }
  1362.  
  1363.     if (queue_interval > 0) {
  1364.     daemon_pid = getpid();
  1365.     write_log(LOG_SYS, "pid %d: smail daemon started", daemon_pid);
  1366.     }
  1367.  
  1368.     /* toss the real uid under which smail was executed */
  1369.     real_uid = getuid();
  1370.  
  1371.     return 0;
  1372. }
  1373.  
  1374. /*
  1375.  * bg_run_queue - perform a queue run in a child process
  1376.  */
  1377. static void
  1378. bg_run_queue(ls)
  1379.     int ls;        /* if >=0, close this descriptor in child */
  1380. {
  1381.     int pid = fork();
  1382.  
  1383.     if (pid == 0) {
  1384.     if (ls >= 0)
  1385.         close(ls);
  1386. #ifdef POSIX_OS
  1387.     (void) setsid();
  1388. #else    /* not POSIX_OS */
  1389.     (void) setpgrp(0, getpid());
  1390. #endif    /* POSIX_OS */
  1391. #ifdef SIGCHLD
  1392.     /* in child process we care about dying kids */
  1393.     (void) signal(SIGCHLD, SIG_DFL);
  1394. #endif
  1395.     (void) alarm(0);
  1396.     do_run_queue();
  1397.     exit(0);
  1398.     }
  1399. }
  1400.  
  1401.  
  1402. /*
  1403.  * verify_addresses - print resolved addresses
  1404.  *
  1405.  * Get a list of addresses and return the output of resolve_addr_list() on
  1406.  * that list.
  1407.  */
  1408. void
  1409. verify_addresses()
  1410. {
  1411.     char *error;
  1412.     struct addr *cur;            /* temp recipient addr list element */
  1413.     struct addr *fail;            /* list of failed addrs */
  1414.     struct addr *defer;            /* list of deferred addrs */
  1415.     struct addr *deliver;        /* addr structures ready to deliver */
  1416.     struct addr **last_addr;        /* pointer to current addr pointer */
  1417.     struct addr *next;
  1418.  
  1419.     X_PANIC_OKAY();
  1420.  
  1421.     if (extract_addresses) {
  1422.     /*
  1423.      * read in the message from stdin, if the -t flag was set.
  1424.      */
  1425.     input_signals();        /* prepare to remove message */
  1426.     if (queue_message(stdin, dot_usage, recipients, &error) == FAIL) {
  1427.         if (errfile) {
  1428.         (void) fprintf(errfile,
  1429.                    "%s: incoming message lost: %s: %s\n",
  1430.                    program,
  1431.                    error,
  1432.                    strerrno());
  1433.         }
  1434.         exitvalue = EX_OSFILE;
  1435.         return;
  1436.     }
  1437.     if (read_message() == NULL) {
  1438.         unlink_spool();
  1439.         (void) fprintf(errfile, "failed to read queued message\n");
  1440.         exitvalue = EX_OSFILE;
  1441.         return;
  1442.     }
  1443.     /* don't actually need the message anymore */
  1444.     unlink_spool();
  1445.     }
  1446.     if (primary_name == NULL) {
  1447.     /* setup all of the hostname information */
  1448.     build_host_strings();
  1449.     }
  1450.     /* figure out who nobody is */
  1451.     compute_nobody();
  1452.  
  1453.  
  1454.     /*
  1455.      * preparse all of the recipient addresses given as arguments.
  1456.      * If we are extracting addresses from the header, then
  1457.      * these addresses are NOT to receive the mail.  To accomplish
  1458.      * this, add them to the hash table so they will be ignored
  1459.      * later.
  1460.      */
  1461.     for (cur = recipients, recipients = NULL; cur; cur = next) {
  1462.     next = cur->succ;
  1463.     split_addr_list(cur->in_addr, &recipients);
  1464.     }
  1465.     last_addr = &recipients;
  1466.     for (cur = recipients; cur; cur = next) {
  1467.     char *error;            /* error from preparse_address */
  1468.  
  1469.     next = cur->succ;
  1470.     if ((cur->work_addr = preparse_address(cur->in_addr, &error)) == NULL)
  1471.     {
  1472.         if (errfile) {
  1473.         (void) fprintf(errfile,
  1474.                    "%s ... syntax error in address: %s\n",
  1475.                    cur->in_addr, error);
  1476.         }
  1477.         /* patch pointer to look at next address */
  1478.         *last_addr = next;
  1479.         xfree((char *)cur);
  1480.         continue;
  1481.     }
  1482.  
  1483.     if (extract_addresses) {
  1484.         (void) add_to_hash(cur->work_addr, (char *)NULL, 0, hit_table);
  1485.         xfree(cur->work_addr);    /* don't need it anymore */
  1486.         xfree((char *)cur);
  1487.         continue;
  1488.     }
  1489.  
  1490.     last_addr = &cur->succ;
  1491.     }
  1492.  
  1493.     if (extract_addresses) {
  1494.     recipients = NULL;        /* don't need them anymore */
  1495.  
  1496.     /*
  1497.      * process_header will get the recipients from the header,
  1498.      * among other things we aren't really interested in here.
  1499.      */
  1500.     error = process_header(&recipients);
  1501.     if (error && errfile) {
  1502.         (void) fprintf(errfile, "error in header: %s\n", error);
  1503.     }
  1504.     }
  1505.  
  1506.     /*
  1507.      * given the list of recipient addresses, turn those
  1508.      * addresses into more specific destinations, including
  1509.      * the transport that is to be used, in the case of
  1510.      * addresses destined remote
  1511.      */
  1512.     deliver = NULL;
  1513.     defer = NULL;
  1514.     fail = NULL;
  1515.     resolve_addr_list(recipients, &deliver, &defer, &fail, TRUE);
  1516.  
  1517.     for (cur = deliver; cur; cur = cur->succ) {
  1518.     if (cur->next_host) {
  1519.         printf("%s at %s ... deliverable\n",
  1520.            cur->next_addr, cur->next_host);
  1521.     } else {
  1522.         printf("%s ... deliverable\n", cur->next_addr);
  1523.     }
  1524.     }
  1525.     for (cur = defer; cur; cur = cur->succ) {
  1526.     printf("%s ... error: %s\n",
  1527.            cur->in_addr, cur->error->message);
  1528.     }
  1529.     for (cur = fail; cur; cur = cur->succ) {
  1530.     printf("%s ... not deliverable: %s\n",
  1531.            cur->in_addr, cur->error->message);
  1532.     }
  1533.     close_system_logs();
  1534. }
  1535.  
  1536.  
  1537. /*
  1538.  * do_run_queue - queue run assuming initial setup has been done
  1539.  */
  1540. static void
  1541. do_run_queue()
  1542. {
  1543.     char **work;            /* vector of jobs */
  1544.  
  1545.     DEBUG(DBG_MAIN_MID, "do_run_queue: called\n");
  1546.  
  1547.     /* get work, and do it with child processes */
  1548.     work = scan_spool_dirs();
  1549.     while (*work) {
  1550.     if (errfile) {
  1551.         (void) fflush(errfile);
  1552.     }
  1553.     if (process_spool_file(*work) == FAIL) {
  1554.         /* fork failed, don't continue */
  1555.         return;
  1556.     }
  1557.  
  1558.     /* message processed, go on to the next message */
  1559.     work++;
  1560.     if (debug && errfile) {
  1561.         (void) putc('\n', errfile);
  1562.     }
  1563.     }
  1564.     DEBUG(DBG_MAIN_HI, "do_run_queue: finished\n");
  1565. }
  1566.  
  1567.  
  1568. /*
  1569.  * print_version - display the current version string on stdout
  1570.  */
  1571. void
  1572. print_version()
  1573. {
  1574.     if (debug > 0) {
  1575.     puts(expand_string("\
  1576. release:    Smail$version, $release_date\n\
  1577. patch number:    #$patch_number, $patch_date\n\
  1578. compilation:    #$compile_num, $compile_date"));
  1579.     } else {
  1580.     puts(version());
  1581.     }
  1582. }
  1583.  
  1584. /*
  1585.  * print_copying_file - print the COPYING file, detailing distribution rights
  1586.  */
  1587. void
  1588. print_copying_file()
  1589. {
  1590.     register FILE *f;
  1591.     register int c;
  1592.  
  1593.     if (copying_file == NULL || (f = fopen(copying_file, "r")) == NULL) {
  1594.     (void) fprintf(stderr, "The file `%s' does not exist.\n\
  1595. Consult the file COPYING in the smail source directory for information\n\
  1596. on copying restrictions and warranty information from the authors\n",
  1597.                copying_file? copying_file: "COPYING");
  1598.     exitvalue = EX_UNAVAILABLE;
  1599.     return;
  1600.     }
  1601.  
  1602.     while ((c = getc(f)) != EOF) {
  1603.     putchar(c);
  1604.     }
  1605.     (void) fclose(f);
  1606. }
  1607.  
  1608. /*
  1609.  * print_variables - write configuration variable values to stdout
  1610.  *
  1611.  * Names of variables are stored in the list of recipients.
  1612.  */
  1613. void
  1614. print_variables()
  1615. {
  1616.     register struct addr *cur;
  1617.     struct addr *new, *next;
  1618.  
  1619.     build_host_strings();
  1620.     /* first reverse the list */
  1621.     new = NULL;
  1622.     for (cur = recipients; cur; cur = next) {
  1623.     next = cur->succ;
  1624.     cur->succ = new;
  1625.     new = cur;
  1626.     }
  1627.     for (cur = new; cur; cur = cur->succ) {
  1628.     print_config_variable(cur->in_addr);
  1629.     }
  1630. }
  1631.  
  1632. /*
  1633.  * print_queue - list the current messages in the mail queue
  1634.  *
  1635.  * If debugging is enabled, print msglog associated with each message.
  1636.  */
  1637. void
  1638. print_queue()
  1639. {
  1640.     char **work;            /* vector of jobs to process */
  1641.     int col;                /* current print column */
  1642.     int save_debug = debug;
  1643.  
  1644.     debug = 0;
  1645.     X_PANIC_OKAY();
  1646.  
  1647.     if (message_bufsiz > 4096) {
  1648.     message_bufsiz = 4096;        /* don't need a big buffer */
  1649.     }
  1650.     work = scan_spool_dirs();
  1651.  
  1652.     while (*work) {
  1653.     char **argv;            /* arguments from spool file */
  1654.     char *error;
  1655.  
  1656.     /* open without locking */
  1657.     if (open_spool(*work, FALSE, &error) == FAIL) {
  1658.         if (errfile) {
  1659.         if (errno == 0) {
  1660.             write_log(LOG_TTY, "%s/%s: %s",
  1661.                   spool_dir, input_spool_fn, error);
  1662.         } else {
  1663.             write_log(LOG_TTY, "%s/%s: %s: %s",
  1664.                   spool_dir, input_spool_fn, error, strerrno());
  1665.         }
  1666.         }
  1667.         work++;
  1668.         continue;
  1669.     }
  1670.     sender = NULL;
  1671.     argv = read_message();
  1672.  
  1673.     if (argv == NULL) {
  1674.         work++;
  1675.         continue;
  1676.     }
  1677.  
  1678.     (void) printf("%s\tFrom: %s  (in %s/input)\n",
  1679.               message_id,
  1680.               sender, spool_dir);
  1681.  
  1682.     (void) printf("\t\tDate: %s\n", get_arpa_date(message_date()));
  1683.  
  1684.     /*
  1685.      * print the argument vectors several to a line, trying not to
  1686.      * go past the 76'th column
  1687.      */
  1688.     if (*argv) {
  1689.         (void) printf("\t\tArgs: %s", *argv);
  1690.         col = 8 + 8 + sizeof("Args: ")-1 + strlen(*argv++);
  1691.     }
  1692.     while (*argv) {
  1693.         if (col + (int)strlen(*argv) > 74) {
  1694.         col = 8 + 8 + sizeof("Args: ") - 1;
  1695.         (void) fputs("\n\t\t      ", stdout);
  1696.         } else {
  1697.         putchar(' ');
  1698.         col++;
  1699.         }
  1700.         col += strlen(*argv);
  1701.         if (strlen(*argv) == 0 || index(*argv, ' ') != NULL) {
  1702.         col += 2;
  1703.         printf("'%s'", *argv++, stdout);
  1704.         } else {
  1705.         fputs(*argv++, stdout);
  1706.         }
  1707.     }
  1708.     putchar('\n');
  1709.     if (save_debug > 0) {
  1710.         send_log(stdout, TRUE, "Log of transactions:\n");
  1711.     }
  1712.     close_spool();
  1713.  
  1714.     work++;                /* next assignment */
  1715.     if (*work) {
  1716.         putchar('\n');
  1717.     }
  1718.     }
  1719. }
  1720.  
  1721.  
  1722. /*
  1723.  * smtp_mode - receive and processes smtp transpactions
  1724.  *
  1725.  * Call receive_smtp() to get incoming messages.  Then, if queue_only mode
  1726.  * is not set, deliver those messages.
  1727.  */
  1728. void
  1729. smtp_mode(in, out)
  1730.     FILE *in;                /* stream of SMTP commands */
  1731.     FILE *out;                /* channel for responses */
  1732. {
  1733.     open_system_logs();
  1734.     if (primary_name == NULL) {
  1735.     build_host_strings();
  1736.     }
  1737.     compute_nobody();
  1738.  
  1739.     /* do the real work */
  1740.     do_smtp(in, out);
  1741. }
  1742.  
  1743. /*
  1744.  * do_smtp - common routine used by smtp_mode() and daemon_mode() for SMTP
  1745.  *
  1746.  * NOTE: When receive_smtp is finished, in and out are closed.
  1747.  */
  1748. static void
  1749. do_smtp(in, out)
  1750.     FILE *in;
  1751.     FILE *out;
  1752. {
  1753.     char **files;            /* files returned by receive_smtp() */
  1754.     int cnt;                /* count of files */
  1755.     int i;
  1756.  
  1757.     /* cache some interesting things */
  1758.     /* send out to process the SMTP transactions */
  1759.     if (out) {
  1760.     X_PANIC_OKAY();
  1761.     } else {
  1762.     X_NO_PANIC();
  1763.     }
  1764.     files = receive_smtp(in, out);
  1765.     X_PANIC_OKAY();
  1766.  
  1767.     (void) fclose(in);
  1768.     if (out) {
  1769.     (void) fclose(out);
  1770.     }
  1771.  
  1772.     /* if we are just queuing input, close and be done with it */
  1773.     if (queue_only || deliver_mode == QUEUE_MESSAGE) {
  1774.     close_spool();
  1775.     return;
  1776.     }
  1777.  
  1778.     for (cnt = 0; files[cnt] != NULL; cnt++) ;
  1779.  
  1780.     /* if delivering more than one mail message, cache driver info */
  1781.     if (cnt > 1) {
  1782.     if (! cached_directors) {
  1783.         cache_directors();
  1784.     }
  1785.     if (! cached_routers) {
  1786.         cache_routers();
  1787.     }
  1788.     if (! cached_transports) {
  1789.         cache_transports();
  1790.     }
  1791.     }
  1792.  
  1793.     /*
  1794.      * process the files last first (if the last file is still open) and
  1795.      * then first to the second to last This ordering is used because the
  1796.      * last one remains open and it requires less overhead if the last
  1797.      * file does not have to be reopened.
  1798.      */
  1799.     for (cnt = 0; files[cnt] != NULL; cnt++) ; /* count the files */
  1800.  
  1801.     if (spool_fn) {
  1802.     /* last file still open, finish processing it */
  1803.     char **argv;            /* args from read_message() */
  1804.     int pid;            /* pid of child process */
  1805.  
  1806.     /* make a child process */
  1807.     /* unlock the message in the parent process (see lock_message()) */
  1808.     unlock_message();
  1809.     pid = fork_wait();
  1810.     if (pid < 0) {
  1811.         /* can't fork(), try again later for all messages */
  1812.         if (errfile) {
  1813.         (void)fprintf(errfile,
  1814.                   "%s: fork() failed: %s, try again later\n",
  1815.                   program, strerrno());
  1816.         (void)fflush(errfile);
  1817.         }
  1818.         return;
  1819.     }
  1820.     if (pid == 0) {
  1821.         /* in child process, process the message */
  1822.         if (lock_message() == FAIL) {
  1823.         /* somebody else grabbed the lock, assume they will deliver */
  1824.         exit(0);
  1825.         }
  1826.         argv = read_message();
  1827.  
  1828.         if (argv == NULL) {
  1829.         exit(exitvalue);
  1830.         }
  1831.  
  1832.         /* process arguments from the spool file */
  1833.         process_args(argv);
  1834.  
  1835.         /* perform delivery */
  1836.         deliver_mail();
  1837.  
  1838.         /* close the system-wide log files */
  1839.         close_system_logs();
  1840.  
  1841.         /* all done with the message */
  1842.         exit(exitvalue);
  1843.     }
  1844.  
  1845.     /*
  1846.      * in the parent
  1847.      *
  1848.      * XXX - we need to close the open spool file, but going through
  1849.      *       routines in spool.c would duplicate efforts already
  1850.      *     done in the child process, so just close it ourselves.
  1851.      */
  1852.     (void) close(spoolfile);
  1853.  
  1854.     --cnt;                /* decrement the count */
  1855.     }
  1856.  
  1857.     /*
  1858.      * process the remaining files
  1859.      */
  1860.     for (i = 0; i < cnt; i++) {
  1861.     /* process_spool_file only returns FAIL on fork() failures */
  1862.     if (process_spool_file(files[i]) == FAIL) {
  1863.         return ;
  1864.     }
  1865.     }
  1866. }
  1867.  
  1868.  
  1869. /*
  1870.  * process_spool_file - open read and process a spool file in a child process
  1871.  *
  1872.  * fork a child to open read and process an input spool file.  Wait for
  1873.  * the child and return when the child has completed processing.
  1874.  *
  1875.  * Return FAIL if the fork() failed, otherwise return SUCCEED.
  1876.  */
  1877. int
  1878. process_spool_file(spfn)
  1879.     char *spfn;                /* spool file name */
  1880. {
  1881.     int pid = fork_wait();
  1882.     char *error;
  1883.  
  1884.     if (pid < 0) {
  1885.     /* can't fork(), try again later */
  1886.     if (errfile) {
  1887.         (void)fprintf(errfile,
  1888.               "%s: fork() failed: %s, try again later\n",
  1889.               program, strerrno());
  1890.         (void)fflush(errfile);
  1891.     }
  1892.     return FAIL;
  1893.     }
  1894.     if (pid == 0) {
  1895.     /* in child process */
  1896.     char **argv;        /* arguments from spool file */
  1897.  
  1898.     /* message grade is encoded in the last char of the filename */
  1899.     msg_grade = spfn[strlen(spfn) - 1];
  1900.  
  1901.     /* initialize state before reading state from the spool file */
  1902.     initialize_state();
  1903.  
  1904.     /* in child process, open the message and attempt delivery */
  1905.     if (open_spool(spfn, TRUE, &error) == FAIL) {
  1906.         if (errno == 0) {
  1907.         write_log(LOG_SYS, "open_spool: %s/%s: %s",
  1908.               spool_dir, input_spool_fn, error);
  1909.         } else {
  1910.         write_log(LOG_SYS, "open_spool: %s/%s: %s: %s",
  1911.               spool_dir, input_spool_fn, error, strerrno());
  1912.         }
  1913.         exit(EX_OSFILE);
  1914.     }
  1915.     argv = read_message();
  1916.  
  1917.     if (argv == NULL) {
  1918.         panic(EX_OSFILE, "failed to read queued message in %s/%s",
  1919.           spool_dir, input_spool_fn);
  1920.         /*NOTREACHED*/
  1921.     }
  1922.  
  1923.     /* process arguments from the spool file */
  1924.     process_args(argv);
  1925.  
  1926.     /* perform delivery */
  1927.     deliver_mail();
  1928.  
  1929.     /* close the sytem-wide log files */
  1930.     close_system_logs();
  1931.  
  1932.     /* all done with the message */
  1933.     exit(exitvalue);
  1934.     }
  1935.  
  1936.     return SUCCEED;
  1937. }
  1938.  
  1939. /*
  1940.  * fork_wait - fork and have the parent wait for the child to complete
  1941.  *
  1942.  * Return with 0 in the child process.
  1943.  * Return with -1 if fork() fails.
  1944.  * Return with the pid in the parent, though the wait() will already
  1945.  *  have been done.
  1946.  */
  1947. int
  1948. fork_wait()
  1949. {
  1950.     int pid = fork();
  1951.     int i;
  1952.  
  1953.     if (pid == 0) {
  1954.     return 0;
  1955.     }
  1956.     if (pid < 0) {
  1957.     return -1;
  1958.     }
  1959.     while ((i = wait((STATUS_TYPE *)0)) >= 0 && i != pid) ;
  1960.  
  1961.     return pid;
  1962. }
  1963.